// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "Components/GameFrameworkInitStateInterface.h"
#include "Components/PawnComponent.h"

#include "LyraPawnExtensionComponent.generated.h"

#define UE_API LYRAGAME_API

namespace EEndPlayReason { enum Type : int; }

class UGameFrameworkComponentManager;
class ULyraAbilitySystemComponent;
class ULyraPawnData;
class UObject;
struct FActorInitStateChangedParams;
struct FFrame;
struct FGameplayTag;

/**
 * 向所有Pawn类添加功能的组件，以便可用于角色/载具等。
 * 这协调其他组件的初始化。
 */
UCLASS(MinimalAPI)
class ULyraPawnExtensionComponent : public UPawnComponent, public IGameFrameworkInitStateInterface
{
	GENERATED_BODY()

public:

	UE_API ULyraPawnExtensionComponent(const FObjectInitializer& ObjectInitializer);

	/** 此整体功能的名称，此功能依赖于其他命名组件功能 */
	static UE_API const FName NAME_ActorFeatureName; // Actor功能名称

	//~ Begin IGameFrameworkInitStateInterface 接口
	virtual FName GetFeatureName() const override { return NAME_ActorFeatureName; } // 获取功能名称
	UE_API virtual bool CanChangeInitState(UGameFrameworkComponentManager* Manager, FGameplayTag CurrentState, FGameplayTag DesiredState) const override; // 检查是否可以改变初始化状态
	UE_API virtual void HandleChangeInitState(UGameFrameworkComponentManager* Manager, FGameplayTag CurrentState, FGameplayTag DesiredState) override; // 处理改变初始化状态
	UE_API virtual void OnActorInitStateChanged(const FActorInitStateChangedParams& Params) override; // Actor初始化状态改变时调用
	UE_API virtual void CheckDefaultInitialization() override; // 检查默认初始化
	//~ End IGameFrameworkInitStateInterface 接口

	/** 如果指定Actor上存在Pawn扩展组件，则返回该组件。 */
	UFUNCTION(BlueprintPure, Category = "Lyra|Pawn")
	static ULyraPawnExtensionComponent* FindPawnExtensionComponent(const AActor* Actor) { return (Actor ? Actor->FindComponentByClass<ULyraPawnExtensionComponent>() : nullptr); } // 查找Pawn扩展组件

	/** 获取Pawn数据，用于在数据中指定Pawn属性 */
	template <class T>
	const T* GetPawnData() const { return Cast<T>(PawnData); } // 获取Pawn数据

	/** 设置当前Pawn数据 */
	UE_API void SetPawnData(const ULyraPawnData* InPawnData);

	/** 获取当前能力系统组件，可能由不同的Actor拥有 */
	UFUNCTION(BlueprintPure, Category = "Lyra|Pawn")
	ULyraAbilitySystemComponent* GetLyraAbilitySystemComponent() const { return AbilitySystemComponent; } // 获取Lyra能力系统组件

	/** 应由拥有的Pawn调用以成为能力系统的化身。 */
	UE_API void InitializeAbilitySystem(ULyraAbilitySystemComponent* InASC, AActor* InOwnerActor);

	/** 应由拥有的Pawn调用以移除自身作为能力系统的化身。 */
	UE_API void UninitializeAbilitySystem();

	/** 应由拥有的Pawn在Pawn的控制器改变时调用。 */
	UE_API void HandleControllerChanged();

	/** 应由拥有的Pawn在玩家状态已复制时调用。 */
	UE_API void HandlePlayerStateReplicated();

	/** 应由拥有的Pawn在设置输入组件时调用。 */
	UE_API void SetupPlayerInputComponent();

	/** 注册到OnAbilitySystemInitialized委托，如果我们的Pawn已注册到能力系统组件，则广播 */
	UE_API void OnAbilitySystemInitialized_RegisterAndCall(FSimpleMulticastDelegate::FDelegate Delegate);

	/** 注册到OnAbilitySystemUninitialized委托，当我们的Pawn被移除为能力系统的化身Actor时触发 */
	UE_API void OnAbilitySystemUninitialized_Register(FSimpleMulticastDelegate::FDelegate Delegate);

protected:

	UE_API virtual void OnRegister() override; // 注册时调用
	UE_API virtual void BeginPlay() override; // 开始游戏时调用
	UE_API virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; // 结束游戏时调用

	/**
	 * Pawn数据复制时调用
	 */
	UFUNCTION()
	UE_API void OnRep_PawnData();

	/** 当我们的Pawn成为能力系统的化身Actor时触发的委托 */
	FSimpleMulticastDelegate OnAbilitySystemInitialized; // 能力系统初始化委托

	/** 当我们的Pawn被移除为能力系统的化身Actor时触发的委托 */
	FSimpleMulticastDelegate OnAbilitySystemUninitialized; // 能力系统取消初始化委托

	/** 用于创建Pawn的Pawn数据。从生成函数或在放置的实例上指定。 */
	UPROPERTY(EditInstanceOnly, ReplicatedUsing = OnRep_PawnData, Category = "Lyra|Pawn")
	TObjectPtr<const ULyraPawnData> PawnData; // Pawn数据

	/** 为方便而缓存的能力系统组件的指针。 */
	UPROPERTY(Transient)
	TObjectPtr<ULyraAbilitySystemComponent> AbilitySystemComponent; // 能力系统组件
};

#undef UE_API